﻿
'在 VisualFreeBasic 选项里，可以选择是不是启用本插件，禁用后，除了 initialization 其它全部失效，也就是 initialization 不受选项控制，必须要执行的。
'VisualFreeBasicStart 函数，除了【启用】选项，还受到 选项里【启动执行】 控制，不选择启动时是不会被执行的。

'由于VFb是32位的，因此编译的 DLL 也必须是32位，不可以是64位DLL
'编译完成后，若无出错，可以按提示选择自动重启VFB生效（选项里已启用此插件才行），重启后自动恢复先前开启的工程。
'假如插件造成VFB无法使用，可以把 VFB\Settings\StartupReBak.txt 文件更名为 VFB\Settings\StartupReplace.txt 后重开软件还原。


Function initialization(xName As String ,xExplain As String) As Long Export '初始化，VFB启动后加载插件时，调用此函数，返回插件名称 （不可执行其它代码）
   '多个插件按优先度依次执行（优先度在VFB选项里设置，每个插件都能执行到）
   '注意：由于此时VFB在做各种初始化工作，加载窗口还在提示中，请勿执行和调用EXE里各个输出函数，避免引发崩溃
   '后面还有 VisualFreeBasicStart 为初始化完成后调用，弹窗及显示功能窗口，在初始化结束后使用。
   '推荐在此做插件的初始化工作，非有必要请勿写在程序入口函数里。
   
   SetFunctionAddress() '设置函数地址 ，必须要做的
   xName    = vfb_LangString("字符转换和插入代码")                                 '插件名，在 标签 上显示的名称
   xExplain = vfb_LangString("代码编辑时，右键菜单里的字符转换和代码插入相关功能") '插件的说明解释，主要时在VFB插件管理里显示，让大家知道插件是干嘛的。
   Function = 3 '返回协议版本号，不同协议（发生接口变化）不能通用，会发生崩溃等问题，因此VFB主软件会判断此版本号，不匹配就不使用本插件。
End Function

Dim Shared CodeEdit_Menu_大写           As Long
Dim Shared CodeEdit_Menu_小写           As Long ' 小写
Dim Shared CodeEdit_Menu_首字母大写     As Long ' 首字母大写
Dim Shared CodeEdit_Menu_转义宽字符类型 As Long ' 转义.W字符类型
Dim Shared CodeEdit_Menu_转义A字符 As Long ' 转义.A字符类型
Dim Shared CodeEdit_Menu_转义UTF8字符 As Long ' 转义.UTF8字符
Dim Shared CodeEdit_Menu_Chr            As Long ' Chr()
Dim Shared CodeEdit_Menu_WChr           As Long ' WChr()
Dim Shared CodeEdit_Menu_utf8编码Chr    As Long ' utf8编码Chr()
Dim Shared CodeEdit_Menu_Base64编码     As Long ' Base64编码
Dim Shared CodeEdit_Menu_解码Base64     As Long ' 解码Base64
Dim Shared CodeEdit_Menu_MD5值          As Long ' MD5值
Dim Shared CodeEdit_Menu_插入(10)        As Long '
Dim Shared MenuID_新增一个过程          As Long ,MenuID_新增一个函数 As Long


Sub MenuAdd(zMenu As HMENU ,nPos As Long ,tFont As HFONT ,ByRef IDC As Long) Export ' 创建VFB主菜单时调用，在这里可以添加菜单（不可执行其它代码）
   'zMenu   菜单句柄
   'nPos    当前位置，0-7 代表：文件 编辑 搜索  视图 工程 工具 帮助 插件
   'tFont   字体句柄，就是符号字体的句柄，需要传递给加载菜单画字体图标用
   'IDC     控件唯一识辨码，在这里作为菜单ID，必须是唯一的，使用后必须 IDC +=1 ，避免产生重复（请勿随便修改，造成VFb混乱）
   ''       自己添加菜单后，自己必须记住自己的 IDC ，好在事件中处理识辨是自己的菜单。
   
   'VFB自己添加完菜单后，再调用这里，这里---{只做添加菜单用，请勿执行其它东西，避免引发崩溃}---
   '注意：由于此时VFB在做各种初始化工作，加载窗口还在提示中，请勿执行和调用EXE里各个输出函数，避免引发崩溃
   ''     只可以用 Menu_Add_Jilu 函数添加，不要用API添加或修改，VFB无法自动处理，发生混乱
   
   '以下为添加菜单例题
   'Menu_Add_Jilu(zMenu, tFont, 图标的符号值,图标样式,IDC, 有效值, 菜单文字, 快捷键)
   '有效值(自动根据状态禁用或启用菜单功能):  =0始终有效 =1代码编辑器时有效 =2窗口区有效 =3有工程时有效 =4窗口和代码
   Select Case nPos
      Case 0 '文件
      Case 1 '编辑
         Menu_Add_Jilu(zMenu ,tFont ,0 ,0 ,0 ,0 ,"" ,"") '分割符号
         MenuID_新增一个过程 = IDC
         Menu_Add_Jilu(zMenu ,tFont ,0 ,&H0 ,IDC ,1 ,vfb_LangString("新增一个过程") ,"")
         IDC                 += 1
         MenuID_新增一个函数 = IDC
         Menu_Add_Jilu(zMenu ,tFont ,0 ,&H0 ,IDC ,1 ,vfb_LangString("新增一个函数") ,"")
         IDC += 1
         
      Case 2 '搜索
      Case 3 '视图
      Case 4 '工程
      Case 5 '工具
      Case 6 '帮助
      Case 7 '插件专用菜单，一般需要什么功能，可以增加到这里
         
      Case 8 '代码编辑时，右键菜单， 字符转换 里的子菜单
         CodeEdit_Menu_大写 = IDC
         Menu_Add_Jilu(zMenu ,tFont ,0 ,&H0 ,IDC ,0 ,vfb_LangString("大写") ,"Ctrl+U")
         IDC                += 1
         CodeEdit_Menu_小写 = IDC
         Menu_Add_Jilu(zMenu ,tFont ,0 ,&H0 ,IDC ,0 ,vfb_LangString("小写") ,"Ctrl+L")
         IDC                      += 1
         CodeEdit_Menu_首字母大写 = IDC
         Menu_Add_Jilu(zMenu ,tFont ,0 ,&H0 ,IDC ,0 ,vfb_LangString("首字母大写") ,"Ctrl+M")
         IDC                          += 1
         CodeEdit_Menu_转义宽字符类型 = IDC
         Menu_Add_Jilu(zMenu ,tFont ,0 ,&H0 ,IDC ,0 ,vfb_LangString("转义.W字符类型") ,"")
         IDC                     += 1
         CodeEdit_Menu_转义A字符 = IDC
         Menu_Add_Jilu(zMenu ,tFont ,0 ,&H0 ,IDC ,0 ,vfb_LangString("转义.A字符类型") ,"")
         IDC                        += 1
         CodeEdit_Menu_转义UTF8字符 = IDC
         Menu_Add_Jilu(zMenu ,tFont ,0 ,&H0 ,IDC ,0 ,vfb_LangString("转义.UTF8字符") ,"")
         IDC += 1
         Menu_Add_Jilu(zMenu ,tFont ,0 ,0 ,0 ,0 ,"" ,"") '分割符号
         CodeEdit_Menu_Chr = IDC
         Menu_Add_Jilu(zMenu ,tFont ,0 ,&H0 ,IDC ,0 ,vfb_LangString("Chr()") ,"")
         IDC                += 1
         CodeEdit_Menu_WChr = IDC
         Menu_Add_Jilu(zMenu ,tFont ,0 ,&H0 ,IDC ,0 ,vfb_LangString("WChr()") ,"")
         IDC                       += 1
         CodeEdit_Menu_utf8编码Chr = IDC
         Menu_Add_Jilu(zMenu ,tFont ,0 ,&H0 ,IDC ,0 ,vfb_LangString("utf8编码Chr()") ,"")
         IDC += 1
         Menu_Add_Jilu(zMenu ,tFont ,0 ,0 ,0 ,0 ,"" ,"") '分割符号
         CodeEdit_Menu_Base64编码 = IDC
         Menu_Add_Jilu(zMenu ,tFont ,0 ,&H0 ,IDC ,0 ,vfb_LangString("Base64编码") ,"")
         IDC                      += 1
         CodeEdit_Menu_解码Base64 = IDC
         Menu_Add_Jilu(zMenu ,tFont ,0 ,&H0 ,IDC ,0 ,vfb_LangString("解码Base64") ,"")
         IDC += 1
         Menu_Add_Jilu(zMenu ,tFont ,0 ,0 ,0 ,0 ,"" ,"") '分割符号
         CodeEdit_Menu_MD5值 = IDC
         Menu_Add_Jilu(zMenu ,tFont ,0 ,&H0 ,IDC ,0 ,vfb_LangString("MD5值") ,"")
         IDC += 1
      Case 9 '代码编辑时，右键菜单， 代码插入 里的子菜单
         Dim i      As Long
         Dim pp(10) As String
         pp(0)  = vfb_LangString("PostMessage")
         pp(1)  = vfb_LangString("SenMessage")
         pp(2)  = vfb_LangString("一行破折号行")
         pp(3)  = vfb_LangString("增加DLL函数声明")
         pp(4)  = vfb_LangString("增加过程")
         pp(5)  = vfb_LangString("增加函数")
         pp(6)  = vfb_LangString("插入当前日期")
         pp(7)  = vfb_LangString("经典调用线程")
         pp(8)  = vfb_LangString("类过程")
         pp(9)  = vfb_LangString("类函数")
         pp(10) = vfb_LangString("类属性")
         For i = 0 To 10
            CodeEdit_Menu_插入(i) = IDC
            Menu_Add_Jilu(zMenu ,tFont ,0 ,&H0 ,IDC ,0 ,pp(i) ,"")
            IDC += 1
         Next
      Case 10 '代码编辑时，右键菜单， 代码格式 里的子菜单
      Case 11 '工程设置菜单，用在工具栏最后面工程类型按钮
      Case 12 '标签菜单 ，用在 TAB0 右键菜单
      Case 13 '代码编辑器，右键菜单
      Case 14 '工程列表，右键菜单
      Case 15 '窗口编辑器，右键菜单
   End Select
   
   
   
   'Menu_Add_Jilu(zMenu, tFont, &HE657, &H0,IDC, 0, ("新建(&N)..."), "Ctrl+N")
   'IDC +=1
   'Menu_Add_Jilu(zMenu, tFont, &HE64D, &H0,IDC, 0, ("打开(&O)..."), "Ctrl+O")
   'IDC +=1
   'Menu_Add_Jilu(zMenu, tFont, &H0,&H0,IDC, 3, ("关闭当前工程(&R)"), "Ctrl+Q")
   'IDC +=1
   'Menu_Add_Jilu(zMenu, tFont, &HE6B2, &H0,IDC, 4, ("保存全部(&E)"), "Ctrl+S")
   'IDC +=1
   'Menu_Add_Jilu(zMenu, tFont, &H0,&H0,IDC, 3, ("另存为模版"), "")
   'IDC +=1
   'Menu_Add_Jilu(zMenu, tFont, 0, 0, 0, 0, "", "")   '分割符号
   'IDC +=1
   'Menu_Add_Jilu(zMenu, tFont, &HE65B, &H0,IDC, 0, ("最近文件"), "Ctrl+T")
   'IDC +=1
   'Menu_Add_Jilu(zMenu, tFont, 0, 0, 0, 0, "", "")
   'IDC +=1
   'Menu_Add_Jilu(zMenu, tFont, &HE637, &H0,IDC, 0, ("命令提示符"), "")
   'IDC +=1
   'Menu_Add_Jilu(zMenu, tFont, 0, 0, 0, 0, "", "")
   'IDC +=1
   'Menu_Add_Jilu(zMenu, tFont, &HE7C2, &H0,IDC, 0, ("退出(&X)"), "")
End Sub

Sub ToolAdd(ByRef IDC As Long) Export '在工具栏 增加按钮（不可执行其它代码）
   '******注意：由于此时VFB在做各种初始化工作，加载窗口还在提示中，请勿执行和调用EXE里各个输出函数，避免引发崩溃*****
   'IDC     控件唯一识辨码，在这里作为菜单ID，必须是唯一的，使用后必须 IDC +=1 ，避免产生重复（请勿随便修改，造成VFb混乱）
   
   '用 InsertTool(position As Long, IcoWchr As Long, Colour As Long, CommandID As Long, xTyep As Long, xTips As String,FileImg As String="") '插入工具栏按钮，此函数只在这里有效果，其它地方无效。
   'position As Long '在此位置插入按钮，从1 开始 到 ** ，分割线也算1个位置，多个插件插入按钮后引起位置改变，注意插件优先度，最后看运行结果。
   '位置 = 0 就不操作，只设置位置，CommandID = 0 表示是分割符
   'IcoWchr   As Long   '宽字符符号值
   'Colour    As Long   '显示的颜色
   'CommandID As Long   '菜单的命令ID号
   'xTyep     As Long   ' 属性  =0始终有效 =1代码编辑器时有效 =2窗口区有效 =3有工程时有效 =4窗口和代码
   'xTips     As String ' 提示
   'FileImg   As String  ' 图标文件名，不包含路径，文件必须在 VFB\Settings\img\tool  里 ，如 "1.ico"
   
End Sub

Sub VisualFreeBasicStart(nThemes As TYPE_THEMES ,nThemesWin As TYPE_THEMES) Export 'VFB 初始结束，可以开始执行其它操作
   '初始化完成后调用，可以在这里弹窗及显示功能窗口，
   '多个插件按优先度依次执行（优先度在VFB选项里设置，每个插件都能执行到）
   ThemeCode = nThemes   '代码主题
   ThemeWin = nThemesWin '窗口主题
   
End Sub
#Define SCI_POSITIONFROMLINE 2167
#Define SCI_GOTOPOS 2025


Function MenuCommand(wID As Long) As Long Export '点击VFB菜单后调用，返回非零后，VFB或优先度低的就不再被执行。等所有插件执行完成后，VFB才执行自己的代码。  wID 是菜单命令ID
   '这里可以根据 wID 执行自己添加的菜单命令，也可以执行别的插件和VFB的命令。
   Select Case wID
      Case CodeEdit_Menu_大写 ' 大写
         ChangeSelectionCase(1) ' 更改代码大小写
      Case CodeEdit_Menu_小写 ' 小写
         ChangeSelectionCase(2) ' 更改代码大小写
      Case CodeEdit_Menu_首字母大写 ' 首字母大写
         ChangeSelectionCase(3) ' 更改代码大小写
      Case CodeEdit_Menu_转义宽字符类型 ' 转义.宽字符类型
         ChangeSelectionCase(10)
      Case CodeEdit_Menu_转义A字符 ' 转义.
         ChangeSelectionCase(11)
      Case CodeEdit_Menu_转义UTF8字符 ' 转义.宽字符类型
         ChangeSelectionCase(12)
      Case CodeEdit_Menu_Chr ' Chr()
         ChangeSelectionCase(4)
      Case CodeEdit_Menu_WChr ' WChr()
         ChangeSelectionCase(5) '
      Case CodeEdit_Menu_utf8编码Chr ' utf8编码Chr()
         ChangeSelectionCase(6) '
      Case CodeEdit_Menu_Base64编码 ' Base64编码
         ChangeSelectionCase(7) '
      Case CodeEdit_Menu_解码Base64 ' 解码Base64
         ChangeSelectionCase(8) '
      Case CodeEdit_Menu_MD5值 ' MD5值
         ChangeSelectionCase(9)
      Case CodeEdit_Menu_插入(0)
         InsertText(StrToUtf8("PostMessage( shWnd , Msg , wParam , lParam )  " & vfb_LangString("'默认为 PostMessageW")))
      Case CodeEdit_Menu_插入(1)
         InsertText(StrToUtf8("SendMessage( shWnd , Msg , wParam , lParam )  " & vfb_LangString("'默认为 SendMessageW")))
      Case CodeEdit_Menu_插入(2)
         InsertText("'--------------------------------------------------------------------------------")
      Case CodeEdit_Menu_插入(3)
         InsertText(StrToUtf8("Declare Function " & vfb_LangString("函数名") & " Lib """ & vfb_LangString("dll文件") & """ Alias """ & vfb_LangString("DLL中的函数名") & """(ByVal eID As Integer  ) As  Integer"))
      Case CodeEdit_Menu_插入(4)
         InsertText(!"\r\nSub Myaaa() \r\n\r\nEnd Sub\r\n")
      Case CodeEdit_Menu_插入(5)
         InsertText(!"\r\nFunction Myaaa() as Long \r\n\r\nEnd Function\r\n")
      Case CodeEdit_Menu_插入(6)
         InsertText("' " & Format(Now ,"yyyy-mm-dd"))
      Case CodeEdit_Menu_插入(7)
         InsertText(StrToUtf8("Threaddetach ThreadCreate(Cast(Any Ptr,@" & vfb_LangString("过程") & ")," & vfb_LangString("参数") & ") '" & vfb_LangString("经典调用方法")))
      Case CodeEdit_Menu_插入(8) ' vfb_LangString("类过程")
         InsertText(!"\r\nDeclare Sub MySub(a As Long)  ' \r\n\r\nSub ClassName.MySub(a As Long) '\r\n\r\nEnd Sub\r\n")
      Case CodeEdit_Menu_插入(9)  ' vfb_LangString("类函数")
         InsertText(!"\r\nDeclare Function MyFunction(a As Long)As Long ' \r\n\r\nFunction ClassName.MyFunction(a As Long)As Long '\r\n\r\nEnd Function\r\n")
      Case CodeEdit_Menu_插入(10) '  vfb_LangString("类属性")
         InsertText(StrToUtf8(!"\r\nDeclare Property MyProperty()As Long '返回属性 \r\nDeclare Property MyProperty(bValue As Long) '给属性赋值 \r\n\r\n"))
         InsertText(StrToUtf8(!"Property ClassName.MyProperty() As Long '返回属性 \r\n\r\nEnd Property\r\nProperty ClassName.MyProperty(bValue As Long)'给属性赋值 \r\n\r\nEnd Property\r\n"))
           
      Case MenuID_新增一个过程 ' 新增一个过程
         Dim aa   As Long    = AppendText(vbCrLf & "Sub MySub()" & vbCrLf & vbCrLf & "End Sub" & vbCrLf & vbCrLf & vbCrLf & vbCrLf)
         Dim pSci As Any Ptr = GetCurrentSci()
         If pSci Then
            Dim nPos As Long = CodeEditMsg(pSci ,SCI_POSITIONFROMLINE ,aa + 2 ,0)
            CodeEditMsg(pSci ,SCI_GOTOPOS ,nPos ,0) '将光标位置插入到函数内部
         End If
      Case MenuID_新增一个函数 ' 新增一个函数
         Dim aa   As Long    = AppendText(vbCrLf & "Function MyFunction() As Long " & vbCrLf & vbCrLf & "End Function" & vbCrLf & vbCrLf & vbCrLf & vbCrLf)
         Dim pSci As Any Ptr = GetCurrentSci()
         If pSci Then
            Dim nPos As Long = CodeEditMsg(pSci ,SCI_POSITIONFROMLINE ,aa + 2 ,0)
            CodeEditMsg(pSci ,SCI_GOTOPOS ,nPos ,0) '将光标位置插入到函数内部
         End if
   End Select
   Function = 0
End Function
Function CodeAttemptAutoInsert(pSci As Any Ptr) As Long Export '代码编辑器里按下回车后，需要处理事情（如自动美化，格式，自动配对等）。返回非零就退出后续操作，优先度低的就无法执行。
   '尝试自动完成for/do/select等块。以及自动美化，格式化。
   '为了效率，就一个插件干这个活即可，其它插件留空，不处理。
   Function = 0
End Function
   
Function CompileStart(ProFile As String, nFile As String) As Long Export  '编译前调用此函数，此时还未生成临时编译文件。返回非零就退出，停止编译，优先度低的就无法执行。
   'ProFile   工程文件，包含文件夹
   'nFile      输出文件，包含文件夹，如软件为 EXE扩展名，DLL为DLL扩展名，64位为 在 release64 路径里。
   
   Function = 0
End Function

Function CompileEnd(ProFile As String, nFile As String) As Long Export  '编译后调用此函数，返回非零就退出，后续操作，优先度低的就无法执行。
   'ProFile   工程文件，包含文件夹
   'nFile      输出文件，包含文件夹，如软件为 EXE扩展名，DLL为DLL扩展名，64位为 在 release64 路径里。
   
   Function = 0
End Function

Sub WinThemeChange(nThemes As TYPE_THEMES) Export '窗口主题已经修改
   ThemeWin = nThemes
   
End Sub

Sub CodeThemeChange(nThemes As TYPE_THEMES) Export '代码主题已经修改
   ThemeCode = nThemes
   
End Sub

Function VisualFreeBasicClose(hWndForm As hWnd) As LResult Export
   'hWndForm   VFB 主窗口，来自 VFB_WM_Close 事件
   '即将关闭窗口，返回非0可阻止关闭  Return True
   
   Function =0 
End Function
Function ChangeSelectionCase(fCase As Long) As Long  ' 更改代码大小写
   Dim pSci As Any Ptr = GetCurrentSci()
   If pSci Then
      Function = Code_ChangeSelectionCaseP(pSci, fCase)
   End If
   
End Function

#Define SCI_SETSELECTIONSTART                           2142
#Define SCI_GETSELECTIONSTART                           2143
#Define SCI_GETSELECTIONEND                             2145
#Define SCI_SETCURRENTPOS                               2141
#Define SCI_SETANCHOR                                   2026
#Define SCI_REPLACESEL                                  2170
#Define SCI_GETTEXTRANGE                                2162

Type Sci_CharacterRange Field = 4
   cpMin As Long   ' long cpMin
   cpMax As Long   ' long cpMax
End Type
Type Sci_TextRange Field = 4
   chrg      As Sci_CharacterRange   ' struct Sci_CharacterRange chrg
   lpstrText As ZString Ptr          ' char *lpstrText
End Type

Function Code_ChangeSelectionCaseP(pSci As Any Ptr ,ByVal fCase As Long) As Long ' 更改代码大小写
   Dim startSelPos As Long   ' Starting position
   Dim endSelPos   As Long   ' Ending position
   Dim strText     As String ' Selected text
   Dim i           As Long
   Dim as String k1 ,k2
   'fCase = 1 (upper case), 2 (lower case), 3 (mixed case)
   'If startSelPos and endSelPos are the same there is not selection,
   startSelPos = CodeEditMsg(pSci ,SCI_GETSELECTIONSTART ,0 ,0)
   endSelPos = CodeEditMsg(pSci ,SCI_GETSELECTIONEND ,0 ,0)
   If startSelPos = endSelPos Then Exit Function
   '     PrintA Str(fCase)
   'Retrieve the text
   strText = Code_GetTextRangeP(pSci ,startSelPos ,endSelPos)
   k1 = Code_GetTextRangeP(pSci ,startSelPos -1 ,startSelPos)
   k2 = Code_GetTextRangeP(pSci ,endSelPos ,endSelPos + 1)
   'Convert it to upper or lower case
   Select Case fCase
      Case 1
         strText = UCase(strText)
      case 2
         strText = LCase(strText)
      case 3
         '始终大写第一个字符，无论
         strText            = LCase(strText)
         Mid(strText ,1 ,1) = UCase(Left(strText ,1))
         If Len(strText) > 1 Then
            For i = 1 To Len(strText) -1
               Select Case strText[i]
                  Case 32 ,95 ,62 ,46 ,40 ' ._>(
                     Mid(strText ,i + 2 ,1) = UCase(Mid(strText ,i + 2 ,1))
               End Select
            Next
         End If
      Case 4 ' 转换为 Chr()
         Dim sc  As String = Utf8toStr(strText)
         dim sct As String
         If Len(sc) > 1 Then
            For i = 0 To Len(sc) -1
               if Len(sct) = 0 Then
                  sct = "Chr(" & sc[i]
               Else
                  sct &= "," & sc[i]
               End if
            Next
            sct &= ") ' " & strText
         End If
         strText = sct
         if k1 = Chr(34) Then startSelPos -= 1
         if k2 = Chr(34) Then endSelPos   += 1
      Case 5 ' 转换为 WChr()
         Dim sc  As CWSTR = UTF8toCWSTR(strText)
         dim sct As String
         If Len(sc) > 1 Then
            For i = 0 To Len(sc) -1
               if Len(sct) = 0 Then
                  sct = "WChr(" & sc[i]
               Else
                  sct &= "," & sc[i]
               End if
            Next
            sct &= ") ' " & strText
         End If
         strText = sct
         if k1 = Chr(34) Then startSelPos -= 1
         if k2 = Chr(34) Then endSelPos   += 1
      Case 6 ' "转换为utf8编码Chr()" ,
         Dim sc As String
         If Len(strText) > 1 Then
            For i = 0 To Len(strText) -1
               if Len(sc) = 0 Then
                  sc = "Chr(" & strText[i]
               Else
                  sc &= "," & strText[i]
               End if
            Next
            sc &= ") ' " & strText
         End If
         strText = sc
         if k1 = Chr(34) Then startSelPos -= 1
         if k2 = Chr(34) Then endSelPos   += 1
      Case 7 ' "转换为Base64编码" ,
         strText = Base64_Encode(Utf8toStr(strText))
      Case 8 ' "转换为解码Base64" ,
         strText = StrToUtf8(Base64_Decode(strText))
      Case 9 ' "转换为 MD5值" ,
         strText = MD5(Utf8toStr(strText))
      Case 10 ' "A字模式转义存W字符" ,
         Dim sc  As CWSTR  = UTF8toCWSTR(strText)
         Dim sct As String = "!"""
         If Len(sc) > 1 Then
            For i = 0 To Len(sc) -1
               sct &= "\u" & Hex(sc[i] ,4)
            Next
            sct &= """  ' " & strText
         End If
         strText = sct
         If k1 = Chr(34) Then startSelPos -= 1
         If k2 = Chr(34) Then endSelPos   += 1
      Case 11
         Dim sc  As String = Utf8toStr(strText)
         Dim sct As String = "!"""
         If Len(sc) > 1 Then
            For i = 0 To Len(sc) -1
               sct &= "\&H" & Hex(sc[i] ,2)
            Next
            sct &= """  ' " & strText
         End If
         strText = sct
         If k1 = Chr(34) Then startSelPos -= 1
         If k2 = Chr(34) Then endSelPos   += 1
      Case 12
         Dim sc  As String = strText
         Dim sct As String = "!"""
         If Len(sc) > 1 Then
            For i = 0 To Len(sc) -1
               sct &= IIf(sc[i] > 31 And sc[i] <= 127 ,Chr(sc[i]) ,"\&H" & Hex(sc[i] ,2))
            Next
            sct &= """  ' " & strText
         End If
         strText = sct
         If k1 = Chr(34) Then startSelPos -= 1
         If k2 = Chr(34) Then endSelPos   += 1
         
         
   End Select
   CodeEditMsg(pSci ,SCI_SETCURRENTPOS ,startSelPos ,0) '选择位置
   CodeEditMsg(pSci ,SCI_SETANCHOR ,endSelPos ,0)       '结束选择
   'Replace the selected text
   CodeEditMsg(pSci ,SCI_REPLACESEL ,0 ,Cast(lParam ,StrPtr(strText)))
   
   Function = 0
End Function
Function Code_GetTextRangeP(pSci As Any Ptr, ByVal cpMin As Long, ByVal cpMax As Long) As String  ' 获取文本范围
   
   Dim p As Long
   Dim buffer As String
   Dim txtrg As SCI_TEXTRANGE
   txtrg.chrg.cpMin = cpMin
   txtrg.chrg.cpMax = cpMax
   buffer = Space(cpMax - cpMin + 1)
   txtrg.lpstrText = StrPtr(buffer)
   CodeEditMsg(pSci, SCI_GETTEXTRANGE, 0, Cast(lParam, @txtrg))
   p = InStr(buffer, Chr(0))
   If p Then buffer = Left(buffer, p - 1)
   Function = buffer
End Function








